home *** CD-ROM | disk | FTP | other *** search
- /*
- * Linux Audio Mixer - with ncurses interface
- *
- * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- *
- * HISTORY:
- *
- * 23/10/93 - Version 0.1 released.
- *
- * 27/10/93 - Doesn't assume existence of any device (volume, bass, etc).
- * - Some minor bug fixes.
- *
- * 30/10/93 - Some bug fixes to work correctly with SB Pro.
- * - Should now work correctly when multiple copies are run
- * simutaneously.
- *
- * 28/11/93 - Version 0.2 released.
- */
-
- /* This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/soundcard.h>
- #include <ncurses.h>
-
- #define BG_COLOR 1
- #define TITLE_COLOR 2
- #define BOTTOM_LINE_COLOR 3
- #define PANEL_COLOR 4
- #define BORDER_COLOR 5
- #define HANDLE_COLOR 6
- #define TRACK_COLOR 7
- #define MARKING1_COLOR 8
- #define MARKING2_COLOR 9
- #define MARKING3_COLOR 10
- #define MARKING4_COLOR 11
- #define MARKING5_COLOR 12
- #define MARKING6_COLOR 13
- #define REC_LED_COLOR 14
- #define PLAY_LED_COLOR 15
- #define ACTIVE_COLOR 16
- #define INACTIVE_COLOR 17
- #define CONTROL_SPACING 8
- #define INCREMENT 2
-
-
- void InitColors(void);
- void DrawHandles(int dev);
- void Adjust(void);
-
-
- /*
- * Global variables
- */
- WINDOW *w_panel;
- int devmask = 0, recmask = 0, recsrc = 0, stereodevs = 0, mixer_fd;
- char *devname[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
- int level[SOUND_MIXER_NRDEVICES];
-
- int main()
- {
- int i, j;
-
- if ((mixer_fd = open("/dev/mixer", O_RDWR)) < 0) {
- fprintf(stderr, "Error opening /dev/mixer.");
- exit(1);
- }
- if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
- perror("SOUND_MIXER_READ_DEVMASK");
- exit(-1);
- }
- if (ioctl(mixer_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1) {
- perror("SOUND_MIXER_READ_RECMASK");
- exit(-1);
- }
- if (ioctl(mixer_fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) {
- perror("SOUND_MIXER_READ_RECSRC");
- exit(-1);
- }
- if (ioctl(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereodevs) == -1) {
- perror("SOUND_MIXER_READ_STEREODEVS");
- exit(-1);
- }
-
-
- if (!devmask) {
- fprintf(stderr, "No device found.");
- exit(-1);
- }
-
- initscr();
- leaveok(stdscr, TRUE);
- keypad(stdscr, TRUE);
- cbreak();
- noecho();
-
- #ifdef COLOR_CHECK
- if (!has_colors())
- fprintf(stderr, "WARNING: no color capability detected.");
- #endif
-
- InitColors();
- move(0, 0);
- attrset(COLOR_PAIR(TITLE_COLOR) | A_BOLD | A_ALTCHARSET);
- printw("%c%c%c Linux Audio Mixer version 0.2"
- " by Savio Lam %c%c%c",
- 178, 177, 176, 176, 177, 178);
- attrset(COLOR_PAIR(BOTTOM_LINE_COLOR) | A_BOLD | A_ALTCHARSET);
- move(LINES-1, 0);
- addstr(" PgUp/PgDn - Prev/Next SPACE - Rec/Play UP/DOWN - Higher/Lower"
- " ESC - Exit ");
- refresh();
-
- w_panel = newwin(LINES - 2, COLS, 1, 0);
- wattrset(w_panel, COLOR_PAIR(PANEL_COLOR) | A_DIM | A_ALTCHARSET);
- wclear(w_panel);
- wattrset(w_panel, COLOR_PAIR(BORDER_COLOR) | A_BOLD | A_ALTCHARSET);
- wborder(w_panel, 219, 219, 223, 220, 219, 219, 219, 219);
-
- /* Draw vertical controls */
- for (i = 0; i < SOUND_MIXER_NRDEVICES-3; i++) {
- for (j = 3; j < 14; j++) {
- if (j < 7)
- wattrset(w_panel, COLOR_PAIR(MARKING1_COLOR) | A_BOLD | A_ALTCHARSET);
- else
- if (j < 11)
- wattrset(w_panel, COLOR_PAIR(MARKING2_COLOR) | A_DIM | A_ALTCHARSET);
- else
- wattrset(w_panel, COLOR_PAIR(MARKING3_COLOR) | A_DIM | A_ALTCHARSET);
- wmove(w_panel, j, i*CONTROL_SPACING+6);
- wprintw(w_panel, "%c %c", 249, 249);
- wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_DIM | A_ALTCHARSET);
- wmove(w_panel, j, i*CONTROL_SPACING+7);
- waddch(w_panel, 179);
- }
- if ((1 << (i+3)) & devmask) {
- DrawHandles(i+3);
- /* Print Rec/Play LED indicators */
- if ((1 << (i+3)) & recmask) {
- wattrset(w_panel,
- COLOR_PAIR(((1 << (i+3)) & recsrc ? REC_LED_COLOR : PLAY_LED_COLOR))
- | A_BOLD | A_ALTCHARSET);
- wmove(w_panel, 2, i*CONTROL_SPACING+7);
- waddch(w_panel, 223);
- }
- wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
- }
- else
- wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_DIM | A_ALTCHARSET);
- /* Draw vertical control labels */
- wmove(w_panel, 15, i*CONTROL_SPACING+6);
- waddstr(w_panel, devname[i+3]);
- }
-
- /* Draw horizontal controls */
- for (i = 1; i < 12; i++) {
- if (i < 5)
- wattrset(w_panel, COLOR_PAIR(MARKING6_COLOR) | A_DIM | A_ALTCHARSET);
- else
- if (i < 9)
- wattrset(w_panel, COLOR_PAIR(MARKING5_COLOR) | A_BOLD | A_ALTCHARSET);
- else
- wattrset(w_panel, COLOR_PAIR(MARKING4_COLOR) | A_BOLD | A_ALTCHARSET);
- wmove(w_panel, 18, i*2+10);
- waddch(w_panel, 254);
- wmove(w_panel, 17, i*2+50);
- waddch(w_panel, 254);
- }
- wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_DIM | A_ALTCHARSET);
- for (i = 1; i < 24; i++) {
- wmove(w_panel, 19, i+10);
- waddch(w_panel, 196);
- wmove(w_panel, 18, i+50);
- waddch(w_panel, 196);
- wmove(w_panel, 20, i+50);
- waddch(w_panel, 196);
- }
-
- if (devmask & SOUND_MASK_VOLUME) {
- DrawHandles(SOUND_MIXER_VOLUME);
- wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
- }
- else
- wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_DIM | A_ALTCHARSET);
- wmove(w_panel, 19, 4);
- waddstr(w_panel, "Volume");
-
- if (devmask & SOUND_MASK_BASS) {
- DrawHandles(SOUND_MIXER_BASS);
- wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
- }
- else
- wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_DIM | A_ALTCHARSET);
- wmove(w_panel, 18, 44);
- waddstr(w_panel, "Bass");
-
- if (devmask & SOUND_MASK_TREBLE) {
- DrawHandles(SOUND_MIXER_TREBLE);
- wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
- }
- else
- wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_DIM | A_ALTCHARSET);
- wmove(w_panel, 20, 44);
- waddstr(w_panel, "Treble");
-
- wrefresh(w_panel);
- Adjust();
-
- close(mixer_fd);
- clear();
- refresh();
- endwin();
-
- return 0;
- }
- /* End of main() */
-
- void InitColors(void)
- {
- start_color();
- init_pair(BG_COLOR, COLOR_WHITE, COLOR_BLACK);
- init_pair(TITLE_COLOR, COLOR_WHITE, COLOR_RED);
- init_pair(BOTTOM_LINE_COLOR, COLOR_CYAN, COLOR_BLUE);
- init_pair(PANEL_COLOR, COLOR_BLACK, COLOR_BLACK);
- init_pair(BORDER_COLOR, COLOR_BLACK, COLOR_BLACK);
- init_pair(HANDLE_COLOR, COLOR_RED, COLOR_BLACK);
- init_pair(TRACK_COLOR, COLOR_WHITE, COLOR_BLACK);
- init_pair(MARKING1_COLOR, COLOR_CYAN, COLOR_BLACK);
- init_pair(MARKING2_COLOR, COLOR_CYAN, COLOR_BLACK);
- init_pair(MARKING3_COLOR, COLOR_BLUE, COLOR_BLACK);
- init_pair(MARKING4_COLOR, COLOR_YELLOW, COLOR_BLACK);
- init_pair(MARKING5_COLOR, COLOR_RED, COLOR_BLACK);
- init_pair(MARKING6_COLOR, COLOR_RED, COLOR_BLACK);
- init_pair(REC_LED_COLOR, COLOR_RED, COLOR_BLACK);
- init_pair(PLAY_LED_COLOR, COLOR_GREEN, COLOR_BLACK);
- init_pair(ACTIVE_COLOR, COLOR_YELLOW, COLOR_WHITE);
- init_pair(INACTIVE_COLOR, COLOR_WHITE, COLOR_BLACK);
- }
- /* End of InitColors() */
-
-
- void DrawHandles(int dev)
- {
- int temp;
-
- if (ioctl(mixer_fd, MIXER_READ(dev), &temp) == -1) {
- perror("MIXER_READ");
- endwin();
- exit(-1);
- }
- if ((1 << dev) & stereodevs) {
- /* Take the average of left and right settings */
- temp = ((temp & 0x7F) + ((temp >> 8) & 0x7F)) / 2;
- temp |= (temp << 8);
- /* Reset so that left and right settings are equal */
- if (ioctl(mixer_fd, MIXER_WRITE(dev), &temp) == -1) {
- perror("MIXER_WRITE");
- endwin();
- exit(-1);
- }
- }
- level[dev] = temp;
- wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
- switch (dev) {
- case SOUND_MIXER_VOLUME:
- wmove(w_panel, 19, 12 + ((temp & 0x7F)+2) / 5);
- waddch(w_panel, 221);
- break;
- case SOUND_MIXER_BASS:
- wmove(w_panel, 18, 52 + ((temp & 0x7F)+2) / 5);
- waddch(w_panel, 221);
- break;
- case SOUND_MIXER_TREBLE:
- wmove(w_panel, 20, 52 + ((temp & 0x7F)+2) / 5);
- waddch(w_panel, 221);
- break;
- default:
- wmove(w_panel, 13 - (((temp & 0x7F)+5) / 10), (dev-3)*CONTROL_SPACING+7);
- waddch(w_panel, 219);
- }
- }
- /* End of DrawHandles() */
-
-
- void Adjust(void)
- {
- int key, incr, dir, dev, temp, temp1;
-
- /* Find first existing device */
- for (dev = 0; !(devmask & (1 << dev)); dev++);
- /* Highlight device label */
- wattrset(w_panel, COLOR_PAIR(ACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
- switch (dev) {
- case SOUND_MIXER_VOLUME:
- wmove(w_panel, 19, 4);
- waddstr(w_panel, "Volume");
- break;
- case SOUND_MIXER_BASS:
- wmove(w_panel, 18, 44);
- waddstr(w_panel, "Bass");
- break;
- case SOUND_MIXER_TREBLE:
- wmove(w_panel, 20, 44);
- waddstr(w_panel, "Treble");
- break;
- default:
- wmove(w_panel, 15, (dev-3)*CONTROL_SPACING+6);
- waddstr(w_panel, devname[dev]);
- }
-
- while (1) {
- wmove(w_panel, 2, 2);
- wrefresh(w_panel);
- key = getch();
- incr = 0;
- dir = 0;
- switch (key) {
- case 27: /* Escape */
- return;
- case KEY_PPAGE: /* Prev Page */
- dir = -1;
- case 9: /* TAB */
- case KEY_NPAGE: /* Next Page */
- if (!dir) /* if not Prev Page pressed */
- dir = 1;
- /* Un-highlight current device label */
- wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
- switch (dev) {
- case SOUND_MIXER_VOLUME:
- wmove(w_panel, 19, 4);
- waddstr(w_panel, "Volume");
- break;
- case SOUND_MIXER_BASS:
- wmove(w_panel, 18, 44);
- waddstr(w_panel, "Bass");
- break;
- case SOUND_MIXER_TREBLE:
- wmove(w_panel, 20, 44);
- waddstr(w_panel, "Treble");
- break;
- default:
- wmove(w_panel, 15, (dev-3)*CONTROL_SPACING+6);
- waddstr(w_panel, devname[dev]);
- }
-
- do { /* Switch to next existing device */
- if (dir == 1) {
- dev++;
- if (dev > SOUND_MIXER_NRDEVICES-1)
- dev = 0;
- }
- else {
- dev--;
- if (dev < 0)
- dev = SOUND_MIXER_NRDEVICES-1;
- }
- } while (!((1 << dev) & devmask));
-
- /* Highlight new device label */
- wattrset(w_panel, COLOR_PAIR(ACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
- switch (dev) {
- case SOUND_MIXER_VOLUME:
- wmove(w_panel, 19, 4);
- waddstr(w_panel, "Volume");
- break;
- case SOUND_MIXER_BASS:
- wmove(w_panel, 18, 44);
- waddstr(w_panel, "Bass");
- break;
- case SOUND_MIXER_TREBLE:
- wmove(w_panel, 20, 44);
- waddstr(w_panel, "Treble");
- break;
- default:
- wmove(w_panel, 15, (dev-3)*CONTROL_SPACING+6);
- waddstr(w_panel, devname[dev]);
- }
- break;
- case ' ': /* Space */
- /* Print Rec/Play LED indicators */
- if ((1 << dev) & recmask) {
- if (recsrc & (1 << dev))
- recsrc &= ~(1 << dev); /* Turn off recording */
- else
- recsrc |= (1 << dev); /* Trun on recording */
- if (ioctl(mixer_fd, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) {
- perror("SOUND_MIXER_WRITE_RECSRC");
- endwin();
- exit(-1);
- }
- wattrset(w_panel, COLOR_PAIR(((1 << dev) & recsrc
- ? REC_LED_COLOR : PLAY_LED_COLOR)) | A_BOLD | A_ALTCHARSET);
- wmove(w_panel, 2, (dev-3)*CONTROL_SPACING+7);
- waddch(w_panel, 223);
- }
- break;
- case '+': /* '+'/UP/RIGHT */
- case KEY_UP:
- case KEY_RIGHT:
- incr = INCREMENT;
- case '-': /* '-'/DOWN/LEFT */
- case KEY_DOWN:
- case KEY_LEFT:
- if (!incr) /* if not '+'/UP/RIGHT pressed */
- incr = -INCREMENT;
- temp = level[dev] & 0x7F;
- temp1 = temp;
- temp += incr;
- if (incr > 0) { /* Increase */
- if (temp > 100)
- temp = 100;
- }
- else /* Decrease */
- if (temp < 0)
- temp = 0;
- temp |= (temp << 8);
- level[dev] = temp;
- if (ioctl(mixer_fd, MIXER_WRITE(dev), &temp) == -1) {
- perror("MIXER_WRITE");
- endwin();
- exit(-1);
- }
- switch (dev) {
- case SOUND_MIXER_VOLUME:
- /* Erase handle from old position */
- wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_ALTCHARSET);
- wmove(w_panel, 19, 12 + (temp1+2) / 5);
- waddch(w_panel, 196);
- /* Draw handle at new position */
- wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
- wmove(w_panel, 19, 12 + ((level[dev] & 0x7F)+2) / 5);
- waddch(w_panel, 221);
- break;
- case SOUND_MIXER_BASS:
- /* Erase handle from old position */
- wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_ALTCHARSET);
- wmove(w_panel, 18, 52 + (temp1+2) / 5);
- waddch(w_panel, 196);
- /* Draw handle at new position */
- wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
- wmove(w_panel, 18, 52 + ((level[dev] & 0x7F)+2) / 5);
- waddch(w_panel, 221);
- break;
- case SOUND_MIXER_TREBLE:
- /* Erase handle from old position */
- wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_ALTCHARSET);
- wmove(w_panel, 20, 52 + (temp1+2) / 5);
- waddch(w_panel, 196);
- /* Draw handle at new position */
- wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
- wmove(w_panel, 20, 52 + ((level[dev] & 0x7F)+2) / 5);
- waddch(w_panel, 221);
- break;
- default:
- /* Erase handle from old position */
- wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_ALTCHARSET);
- wmove(w_panel, 13 - ((temp1+5) / 10),
- (dev-3)*CONTROL_SPACING+7);
- waddch(w_panel, 179);
- /* Draw handle at new position */
- wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
- wmove(w_panel, 13 - (((level[dev] & 0x7F)+5) / 10),
- (dev-3)*CONTROL_SPACING+7);
- waddch(w_panel, 219);
- }
- break;
- }
- }
- }
- /* End of Adjust() */
-